<template>
  <div class="formWidgetGroup">
    <template v-for="(rowItem, index) in _structure">
      <cim-row v-if="Array.isArray(rowItem)" :key="`row${index}`">
        <template v-if="Array.isArray(rowItem)">
          <cim-col
            v-for="item in rowItem"
            :key="item.key"
            :span="item.span"
          >
            <cim-form-item
              :label="item.label"
              :prop="item.key"
              :validation="item.validation"
              :trigger="item.trigger"
              :style="{
                boxSize: 'border-box',
                padding: item.padding,
                marginBottom: item.marginBottom
              }"
              :class="[`label--${configuration.labelPosition || 'right'}`]"
              v-if="!(item.hideWhenEmpty && item.options && !item.options.length)"
            >
              <template v-for="widget in allWidgets">
                <component
                  :is="widget.component"
                  :key="widget.type"
                  v-if="item.type === widget.type"
                  v-bind="item.attrs"
                  v-on="item.on"
                  :value="formData[item.key]"
                  :style="{ marginBottom: 0 }"
                ></component>
              </template>

              <p
                v-if="item.description"
                class="formWidgetGroup__desc"
                :style="{
                  position: configuration.descPosition
                }"
                @click="() => handleClickDescription(item.key, item.replaceValue)"
              >
                {{ item.description }}
              </p>
            </cim-form-item>
          </cim-col>
        </template>
      </cim-row>

      <p
        v-else-if="rowItem.title"
        :key="`title${index}`"
        class="formWidgetGroup__rowTitle"
        :style="rowItem.style"
      >
        {{ rowItem.title }}
      </p>
    </template>
  </div>
</template>

<script>
import Vue from 'vue'
import '../../../styles/form-widget-group.less'
import { CimRow, CimCol, CimFormItem, CimInput, CimSelect, CimDatePicker, CimAutocomplete, CimCheckboxGroup } from '../../../index'

Vue.use(CimRow)
Vue.use(CimCol)
Vue.use(CimFormItem)

export default {
  name: 'CimFormWidgetGroup',
  props: {
    structure: {
      type: Array,
      default: () => []
    },
    formData: {
      type: Object,
      default: () => ({})
    },
    configuration: {
      type: Object,
      default: () => ({})
    },
    widgets: {
      type: Array,
      default: () => [],
      validator (arr) {
        return arr.every(item => item.component && item.type)
      }
    }
  },
  data () {
    return {
      initWidgets: [
        {
          component: CimInput,
          type: 'input'
        },
        {
          component: CimSelect,
          type: 'select'
        },
        {
          component: CimDatePicker,
          type: 'date-picker'
        },
        {
          component: CimAutocomplete,
          type: 'autocomplete'
        },
        {
          component: CimCheckboxGroup,
          type: 'checkbox'
        }
      ],
      showAutoCompleteWrap: false
    }
  },
  computed: {
    allWidgets () {
      return this.initWidgets.concat(this.widgets)
    },
    _structure () {
      let { marginBottom, size, gutter } = this.configuration
      const _this = this

      return this.structure.map(item => {
        if (!Array.isArray(item)) return item

        let spanSum = 0

        return item.map((widget, index) => {
          let { marginBottom: itemMB, span, attrs, on, key } = widget
          let { size: itemSize } = attrs || {}
          let { input, blur } = on || {}
          let pdLeft = 0
          let pdRight = 0

          spanSum += widget.span || 24 / item.length
          if (gutter) {
            pdLeft = index === 0 ? 0 : gutter / 2
            pdRight = spanSum >= 24 ? 0 : gutter / 2
          }

          return Object.assign({}, widget, {
            marginBottom: (itemMB === undefined ? (marginBottom !== undefined ? marginBottom : 16) : itemMB) + 'px',
            span: span || 24 / item.length,
            padding: `0 ${pdRight}px 0 ${pdLeft}px`,
            attrs: Object.assign({}, attrs, {
              size: itemSize || size
            }),
            on: Object.assign({}, on, {
              input (...args) {
                if (typeof input === 'function') input(...args)
                _this.$emit('update:formData', Object.assign({}, _this.formData, {
                  [key]: args[0]
                }))
              },
              blur (...args) {
                if (typeof blur === 'function') blur(...args)

                let value = _this.formData[key]

                if (typeof value === 'string') {
                  _this.$emit('update:formData', Object.assign({}, _this.formData, {
                    [key]: value.trim()
                  }))
                }
              }
            })
          })
        })
      })
    }
  },
  methods: {
    handleClickDescription (key, val) {
      if (val) {
        this.$emit('update:formData', Object.assign({}, this.formData, { [key]: val }))
      }
    }
  },
  created () {
    this.allWidgets.forEach(item => {
      Vue.use(item.component)
    })
  }
}
</script>
